/*
 *  RendererGLES1.cpp
 *  SypXIPhone
 *
 *  Created by Luv Khemani on 5/11/10.
 *  Copyright 2010 Luv Khemani. All rights reserved.
 *
 */
#include "RendererGLES1.h"
#include "Mesh.h"
#include "MeshInstance.h"
#include "Texture.h"

#ifdef SYPX_PLATFORM_IPHONE
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#endif

#include <glm/gtc/type_ptr.hpp>
#include <iostream>

namespace SypX
{

	RendererGLES1::RendererGLES1()
	{

	}
	RendererGLES1::~RendererGLES1()
	{
		if(glGetError() != GL_NO_ERROR)
		{
			std::cout<<"GL Error encountered\n";
		}
	}


	void RendererGLES1::createTexture(Texture* tex)
	{
		glGenTextures(1, &tex->getTexIDRef());
		glBindTexture(GL_TEXTURE_2D, tex->getTexIDRef());
		///Linear Filtering
		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexImage2D(GL_TEXTURE_2D, 0, tex->getInternalFormat(), tex->getWidth(), tex->getHeight(), 0, tex->getDataFormat() , GL_UNSIGNED_BYTE, &tex->getDataRef()[0]);
	}

	void RendererGLES1::deleteTexture(Texture* tex)
	{
		glDeleteTextures(1, &tex->getTexIDRef());
	}

	void RendererGLES1::clearScreen(bool color, bool depth)
	{
		if(color && depth)
		{
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		}

	}

	void RendererGLES1::setClearScreenColor(const Vec4& color )
	{
		Renderer::setClearScreenColor(color);
		glClearColor(color.r, color.g, color.b, color.a);
	}

	void RendererGLES1::drawMesh(MeshInstance* mi)
	{
		Mesh* m = mi->getMesh();
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadMatrixf( glm::value_ptr(mi->getTransformMatrix()) );
		glEnableClientState(GL_VERTEX_ARRAY);

		if(m->usesColor())
		{
			glEnableClientState(GL_COLOR_ARRAY);
		}
		else
		{//i dunno why not setting the color screws up shit, but just set it
			glColor4f(activeColor.r, activeColor.g, activeColor.b, activeColor.a);
		}

		Texture* t = mi->getTexture();

		FloatArray& d = m->getDataArrayRef();
		glVertexPointer(3,GL_FLOAT,m->getStride(), &(d[0]) );

		if(t)
		{
			glBindTexture(GL_TEXTURE_2D, t->getTexIDRef());
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glTexCoordPointer(2,GL_FLOAT,m->getStride(),(char*)&(d[3]) );
		}
		else
		{
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		}

		if(m->usesColor())
		{
			glColorPointer(4, GL_FLOAT, m->getStride(), (char*)&(d[5]));
		}
		glDrawArrays(m->getPrimitiveType(), 0, m->getNumVertices());

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

		glPopMatrix();
	}

	void RendererGLES1::init(UInt width, UInt height)
	{
		Renderer::init(width,height);//Call base class

		glGenFramebuffersOES(1, &framebuffer);						//Gen FBO
		glGenRenderbuffersOES(1, &renderbuffer);					//Gen color RBO (or backbuffer if u will)
		glGenRenderbuffersOES(1, &depthbuffer);						//Gen DepthBuffer
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthbuffer);
		glRenderbufferStorageOES(GL_RENDERBUFFER_OES,
								 GL_DEPTH_COMPONENT16_OES,
								 width,
								 height);

		glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);		//Bind FBO
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, renderbuffer);	//Bind Backbuffer

		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
									 GL_RENDERBUFFER_OES, renderbuffer);//Bind RBO/Backbuffer to FBO
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
									 GL_DEPTH_ATTACHMENT_OES,
									 GL_RENDERBUFFER_OES,
									 depthbuffer);

		glViewport(0, 0, width, height);//Set Viewport

		glEnable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);  //No normals so disable lighting
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0);

		glEnable (GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrthof(0, width, 0, height,-1.5f,1.5f);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

	}

}
